package com.ts.opengl.render

import android.content.Context
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.opengl.GLES20.GL_ARRAY_BUFFER
import android.opengl.GLES20.GL_CLAMP_TO_EDGE
import android.opengl.GLES20.GL_COLOR_ATTACHMENT0
import android.opengl.GLES20.GL_ELEMENT_ARRAY_BUFFER
import android.opengl.GLES20.GL_FLOAT
import android.opengl.GLES20.GL_FRAMEBUFFER
import android.opengl.GLES20.GL_LINEAR
import android.opengl.GLES20.GL_NONE
import android.opengl.GLES20.GL_RGBA
import android.opengl.GLES20.GL_STATIC_DRAW
import android.opengl.GLES20.GL_STREAM_DRAW
import android.opengl.GLES20.GL_TEXTURE_2D
import android.opengl.GLES20.GL_TEXTURE_MAG_FILTER
import android.opengl.GLES20.GL_TEXTURE_MIN_FILTER
import android.opengl.GLES20.GL_TEXTURE_WRAP_S
import android.opengl.GLES20.GL_TEXTURE_WRAP_T
import android.opengl.GLES20.GL_UNSIGNED_BYTE
import android.opengl.GLES20.glBindBuffer
import android.opengl.GLES20.glBindFramebuffer
import android.opengl.GLES20.glBindTexture
import android.opengl.GLES20.glBufferData
import android.opengl.GLES20.glEnableVertexAttribArray
import android.opengl.GLES20.glFramebufferTexture2D
import android.opengl.GLES20.glGenFramebuffers
import android.opengl.GLES20.glGenTextures
import android.opengl.GLES20.glTexImage2D
import android.opengl.GLES20.glTexParameteri
import android.opengl.GLES20.glTexSubImage2D
import android.opengl.GLES20.glVertexAttribPointer
import android.opengl.GLES30
import android.opengl.GLES30.GL_PIXEL_PACK_BUFFER
import android.opengl.GLES30.GL_PIXEL_UNPACK_BUFFER
import android.opengl.GLES30.glBindVertexArray
import android.opengl.GLSurfaceView
import android.opengl.GLUtils
import com.ts.audiocamera.R
import com.ts.opengl.simpleDraw.openglUtil
import java.nio.ByteBuffer
import javax.microedition.khronos.egl.EGLConfig
import javax.microedition.khronos.opengles.GL10


class PBORender(var context:Context):GLSurfaceView.Renderer {

    var vVertices= floatArrayOf(
        -1.0f,-1.0f,0.0f,
        1.0f,-1.0f,0.0f,
        -1.0f,1.0f,0.0f,
        1.0f,1.0f,0.0f
    );

    var vTexCoors= floatArrayOf(
        0.0f, 1.0f,
        1.0f, 1.0f,
        0.0f, 0.0f,
        1.0f, 0.0f,
    )

    val vvFboTexCoors= floatArrayOf(
        0.0f, 0.0f,
        1.0f, 0.0f,
        0.0f, 1.0f,
        1.0f, 1.0f,
    )


    val indices=intArrayOf(0, 1, 2, 1, 3, 2)

    val indicesBuffer by lazy{
        openglUtil.createIntBuffer(indices);
    }

    val vFboTexureCoorsBuffer by lazy{
        openglUtil.createFloatBuffer(vvFboTexCoors);
    }
    val vVerticesBuffer by lazy {
        openglUtil.createFloatBuffer(vVertices);
    }

    val vTexCoorsBuffer by lazy {
        openglUtil.createFloatBuffer(vTexCoors);
    }

    var mUploadPboIds=FloatArray(2);

    var mDownloadPboIds=FloatArray(2);
    var progeam=0

    var programfbo=0;

    var m_VboIds=IntArray(4)

    var m_VaoIds= intArrayOf(2)

    var width=0;
    var height=0;


    override fun onSurfaceCreated(gl: GL10?, config: EGLConfig?) {

        progeam=openglUtil.createProgram(context, R.raw.pbo_render_vert,R.raw.pbo_render_frag)


        //生成vbo
        GLES30.glGenBuffers(m_VboIds.size,m_VboIds,0)
        //vbo数据绑定==========================================================================
        GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER,m_VboIds[0])
        GLES30.glBufferData(GLES30.GL_ARRAY_BUFFER,vVerticesBuffer.capacity(),vVerticesBuffer,GL_STATIC_DRAW)

        GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER,m_VboIds[1])
        GLES30.glBufferData(GLES30.GL_ARRAY_BUFFER,vTexCoorsBuffer.capacity(),vTexCoorsBuffer,GL_STATIC_DRAW)


        GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER,m_VboIds[2])
        GLES30.glBufferData(GLES30.GL_ARRAY_BUFFER,vFboTexureCoorsBuffer.capacity(),vFboTexureCoorsBuffer,GL_STATIC_DRAW)

        GLES30.glBindBuffer(GLES30.GL_ELEMENT_ARRAY_BUFFER,m_VboIds[3])
        GLES30.glBufferData(GLES30.GL_ELEMENT_ARRAY_BUFFER,indicesBuffer.capacity(),indicesBuffer,GL_STATIC_DRAW)


        //结束vbo数据绑定==========================================================================


        //生成vao
        GLES30.glGenVertexArrays(m_VaoIds.size,m_VaoIds,0)
        //绑定vao
        glBindVertexArray(m_VboIds[0])


        //两个vao  一个普通 一个离屏渲染
        glBindBuffer(GL_ARRAY_BUFFER,m_VboIds[0])
        glEnableVertexAttribArray(0)
        glVertexAttribPointer(0,3,GLES30.GL_FLOAT,false,3,0)
        glBindBuffer(GL_ARRAY_BUFFER, GL_NONE)


        glBindBuffer(GL_ARRAY_BUFFER,m_VboIds[1])
        glEnableVertexAttribArray(1)
        glVertexAttribPointer(1,2,GLES30.GL_FLOAT,false,2,0)
        glBindBuffer(GL_ARRAY_BUFFER, GL_NONE)

        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,m_VboIds[3])
        glBindVertexArray(GL_NONE);

////------------------------------结束普通vao
        //绑定vao
        glBindVertexArray(m_VaoIds[1])
        glBindBuffer(GL_ARRAY_BUFFER, m_VboIds[0])
        glEnableVertexAttribArray(0)
        glVertexAttribPointer(0, 3, GL_FLOAT, false, 3 ,0)
        glBindBuffer(GL_ARRAY_BUFFER, GL_NONE)

        glBindBuffer(GL_ARRAY_BUFFER, m_VboIds[2])
        glEnableVertexAttribArray(1)
        glVertexAttribPointer(1, 2, GL_FLOAT, false, 2 ,0)
        glBindBuffer(GL_ARRAY_BUFFER, GL_NONE)

        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_VboIds[3]);
        ////------------------------------结束离开vao


        glGenTextures(m_ImageTextureId.size,m_ImageTextureId,0)
        glBindTexture(GLES30.GL_TEXTURE_2D, m_ImageTextureId[0]);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

        val bitmap=BitmapFactory.decodeFile(context.resources.getResourceName(R.drawable.recipe_1))
        width=bitmap.width;
        height=bitmap.height;
        GLUtils.texImage2D(GL_TEXTURE_2D,0,bitmap,0)
        glBindTexture(GL_TEXTURE_2D, GL_NONE);


        GLES30.glGenBuffers(m_UploadPboIds.size,m_UploadPboIds,0);
        val imageSize=bitmap.width*bitmap.height*4;
        GLES30.glBindBuffer(GL_PIXEL_UNPACK_BUFFER,m_UploadPboIds[0])
        glBindBuffer(GL_PIXEL_UNPACK_BUFFER, m_UploadPboIds[0]);
        glBufferData(GL_PIXEL_UNPACK_BUFFER, imageSize, null, GL_STREAM_DRAW);
        glBindBuffer(GL_PIXEL_UNPACK_BUFFER, m_UploadPboIds[1]);
        glBufferData(GL_PIXEL_UNPACK_BUFFER, imageSize, null, GL_STREAM_DRAW);
        glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);



        GLES30.glGenBuffers(m_DownloadPboIds.size,m_DownloadPboIds,0);
//        var imageSize=bitmap.width*bitmap.height*4;
        GLES30.glBindBuffer(GL_PIXEL_PACK_BUFFER,m_DownloadPboIds[0])
        glBindBuffer(GL_PIXEL_PACK_BUFFER, m_DownloadPboIds[0]);
        glBufferData(GL_PIXEL_PACK_BUFFER, imageSize, null, GL_STREAM_DRAW);
        glBindBuffer(GL_PIXEL_PACK_BUFFER, m_DownloadPboIds[1]);
        glBufferData(GL_PIXEL_PACK_BUFFER, imageSize, null, GL_STREAM_DRAW);
        glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);

        CreateFrameBufferObj(bitmap);

        bitmap.recycle()
    }

    var m_FboTextureId=IntArray(1);
    var m_DownloadPboIds= intArrayOf(2);
    var m_UploadPboIds= intArrayOf(2);
    var m_ImageTextureId= intArrayOf(1)

    var m_FboId=IntArray(1)
    fun CreateFrameBufferObj(bitmap: Bitmap){
        glGenTextures(m_FboTextureId.size,m_FboTextureId,0);
        glBindTexture(GL_TEXTURE_2D,m_FboTextureId[0]);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glBindTexture(GL_TEXTURE_2D, GL_NONE);


        glGenFramebuffers(m_FboId.size,m_FboId,0)
        GLES30.glBindBuffer(GLES30.GL_FRAMEBUFFER,m_FboId[0])
        GLES30.glBindTexture(GLES30.GL_TEXTURE_2D,m_FboTextureId[0]);
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,GL_TEXTURE_2D,m_FboTextureId[0],0)

        glTexImage2D(GL_TEXTURE_2D,0, GL_RGBA,bitmap.width,bitmap.height,0,GL_RGBA,GLES30.GL_UNSIGNED_BYTE,null)

        glBindTexture(GL_TEXTURE_2D, GL_NONE);
        glBindFramebuffer(GL_FRAMEBUFFER, GL_NONE);
    }

    override fun onSurfaceChanged(gl: GL10?, width: Int, height: Int) {
        GLES30.glViewport(0,0,this.width,this.height);
    }

    override fun onDrawFrame(gl: GL10?) {
        GLES30.glViewport(0,0,this.width,this.height);
    }

    fun UploadPixels(){
        var dataSize=width*height*4;

        val bitmap=BitmapFactory.decodeFile(context.resources.getResourceName(R.drawable.recipe_1))
        glBindTexture(GL_TEXTURE_2D,m_ImageTextureId[0]);
        val bytes: Int = bitmap.getByteCount()
        val buf = ByteBuffer.allocate(bytes)
        bitmap.copyPixelsToBuffer(buf)
        //替换纹理
        glTexSubImage2D(GL_TEXTURE_2D,0,0,0,width,height, GL_RGBA,GL_UNSIGNED_BYTE,buf)
        bitmap.recycle()







    }
}